﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;

namespace ZOIL.DataModel
{
    public class ViewModelCollectionSynchronizer<V, M>
    {
        private readonly IList<M> _modelCollection;
        private readonly IList<V> _viewModelCollection;
        private readonly IViewModelConverter<V, M> _viewModelConverter;

        public ViewModelCollectionSynchronizer(IList<V> viewModel, IList<M> model, IViewModelConverter<V, M> converter, bool copyModelToViewModel)
        {
            _viewModelConverter = converter;
            _viewModelCollection = viewModel;
            _modelCollection = model;

            if (copyModelToViewModel)
            {
                initWithModelAsSource();
            }

            (_viewModelCollection as INotifyCollectionChanged).CollectionChanged += _viewModelCollection_CollectionChanged;
            (_modelCollection as INotifyCollectionChanged).CollectionChanged += _modelCollection_CollectionChanged;
        }

        private void initWithModelAsSource()
        {
            _viewModelCollection.Clear();

            foreach (M m in _modelCollection)
            {
                V vm = _viewModelConverter.getViewModel(m);
                _viewModelCollection.Add(vm);
            }
        }

        private void _modelCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    foreach (Object o in e.NewItems)
                    {
                        var m = (M) o;
                        if (m != null)
                        {
                            V vm = _viewModelConverter.getViewModel(m);
                            _viewModelCollection.Add(vm);
                        }
                    }
                    break;
                case NotifyCollectionChangedAction.Move:
                    break;
                case NotifyCollectionChangedAction.Remove:
                    foreach (Object o in e.OldItems)
                    {
                        var m = (M) o;
                        if (m != null)
                        {
                            _viewModelCollection.Remove(_viewModelCollection.Where(vm => _viewModelConverter.getModel(vm).Equals(m)).Single());
                        }
                    }
                    break;
                case NotifyCollectionChangedAction.Replace:
                    break;
                case NotifyCollectionChangedAction.Reset:
                    break;
                default:
                    break;
            }
        }

        private void _viewModelCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            Console.WriteLine("ViewModelCollection Changed: " + sender);
        }
    }
}